Release 10.1A: OpenEdge Development:
ProDataSets
Forcing the ProDataSet to be passed BY-VALUE
If you were paying attention, you will have noticed that there’s an extra keyword on the ProDataSet parameter at the top of
fetchOrders, as shown:
Why is this here? After all, as you learned earlier, passing ProDataSets by value (that is, by copying the data from one procedure to the other) is the default behavior, and you have to explicitly specify
BY-REFERENCEin theRUNstatement to pass the ProDataSet by simply pointing the called procedure at the same instance the calling procedure is using.To answer the question, let’s look at a sketch of how the ProDataSet definitions are used in these two procedures, the window procedure that represents the client and the support procedure that represents the server code, as shown in Figure 7–1.
Figure 7–1: Use of ProDataSet definitions
![]()
Here are the steps the procedures go through using the default behavior of passing the ProDataSet by value:
- The ProDataSet that is going to supply the data to the client is defined in
orderSupport.p. TheSET-CALLBACK-PROCEDUREmethods that attach its behavior to it all point to that definition by using the local ProDataSet handle or one of its buffer handles.- When the client procedure calls
fetchOrders, the ProDataSet parameter infetchOrdersalso references the local ProDataSetdsOrderwhose definition it shares.- When
fetchOrdersdoes aFILL, thatFILLalso references the local ProDataSetdsOrder.- Because the
FILLcallback events have been attached to that local instance ofdsOrder, they all execute correctly to prepare the query, attach Data-Sources, and take other actions as part of theFILL.- When
fetchOrdersreturns ProDataSetdsOrderasOUTPUT, it again refers to the local ProDataSet, which is copied back to the window procedure’s own instance of ProDataSetdsOrder.In this way, the ProDataSet in
orderSupport.p(enclosed in the dotted line) maintains its integrity. All the behavior that has been attached to it executes properly. This is always how a procedure call like this operates when the application is actually distributed. If the window procedure truly executes in a client session and the support procedure in an AppServer session, then the ProDataSet is always copied back to the client from the server. Given this expectation, the way you have set up the server procedure is entirely appropriate.However, you also want to code your procedures so that even when they are all run in the same session, even if only for initial testing purposes, they run correctly. Because ProDataSets are passed by value by default, the default behavior in a strictly local situation is also correct. The potential problem lies in the fact that
orderSupport.pdepends on the ProDataSet always being passed by value. Figure 7–2 shows what happens if the client procedure in the same session decides to ask for theOUTPUTDATASETdsOrderBY-REFERENCE.Figure 7–2: ProDataSet in an AppServer session
![]()
The following describes the execution flow in Figure 7–2:
- The
SET-CALLBACK-PROCEDUREmethods still act on the ProDataSet instance inorderSupport.p.- When the window procedure runs
fetchOrderslocally with the ProDataSet passedBY-REFERENCE, it is forcing the support procedure to use its instance ofdsOrderin order to avoid copying the ProDataSet back.- Because Progress adjusts the parameter reference to
dsOrderinfetchOrdersto point to the ProDataSet in the caller, theFILLis done relative to the ProDataSet in the window procedurePickOrder.w.- Unfortunately, the callback procedures are still attached to the (now unused) ProDataSet instance in
orderSupport.p. Therefore they don’t run when theFILLhappens because theFILLis on a different instance of the ProDataSet.- When
fetchOrdersreturns, it doesn’t copy anything back toPickOrder.wbecause theBY-REFERENCEqualifier tells Progress to use the caller’s instance of the ProDataSet. Because the fill events never fire to prepare the query and attach the Data-Sources, nothing happened and there is no data on the client.The design of
orderSupport.pin this case requires that the ProDataSet be passed by value. For this reason, you can assure that the calls will be made properly by forcing the parameter to be passed by value by using theBY-VALUEkeyword on the parameter definition in the called procedure. Then everything works properly even if a local caller tries to useBY-REFERENCE. The qualifier is simply overridden by the definition in the called procedure, without error.As with the earlier discussion about when and how to use
BY-REFERENCE, the implications of its use can seem confusing. The best guideline is to pass ProDataSetsBY-REFERENCEwhen you expect that the procedure call will always, or at least sometimes, be made locally (within the same session) in the deployed application (where performance counts), and when you have structured your procedures such that you won’t have references to the wrong ProDataSet instance, as could happen in the second example here. Passing a ProDataSetBY-REFERENCEcan be a valuable optimization, but it is only an optimization, and you must always make sure that sharing the same ProDataSet instance won’t have unintended consequences.Now, let’s return to completing the example.
|
Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095 |